package mapkit.handlers
{
	import flash.events.MouseEvent;
	import flash.geom.Point;

	import mapkit.MapHandler;
	import mapkit.MapHandlerEvent;
	import mapkit.carto.Envelope;
	import mapkit.carto.Location;

	public class MouseDefaults extends MapHandler
	{
		private var _zoomStep:Number=0.8;

		public function get zoomStep():Number
		{
			return _zoomStep;
		}

		public function set zoomStep(value:Number):void
		{
			_zoomStep=value;
		}

		private var _zoomThreshold:Number=2;

		public function get zoomThreshold():Number
		{
			return _zoomThreshold;
		}

		public function set zoomThreshold(value:Number):void
		{
			_zoomThreshold=value;
		}

		override public function get keyboardLocked():Boolean
		{
			return false;
		}

		override public function get mouseLocked():Boolean
		{
			return true;
		}

		override protected function load():void
		{
			super.load();
			map.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			map.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			map.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			map.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			map.addEventListener(MouseEvent.CLICK, clickHandler);

			addEventListener(MouseDefaultsEvent.DRAG_START, dragStartHandler);
			addEventListener(MouseDefaultsEvent.DRAG_END, dragCompleteHandler);
		}

		override protected function unload():void
		{
			map.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			map.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			map.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			map.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			map.removeEventListener(MouseEvent.CLICK, clickHandler);

			removeEventListener(MouseDefaultsEvent.DRAG_START, dragStartHandler);
			removeEventListener(MouseDefaultsEvent.DRAG_END, dragCompleteHandler);
			super.unload();
		}

		private var _origin:Location=null;

		private var _dragPhase:int=MapHandlerEvent.IDLE;

		protected function mouseDownHandler(event:MouseEvent):void
		{
			switch (_dragPhase)
			{
				case MapHandlerEvent.IDLE:
					_dragPhase=MapHandlerEvent.START;
					break;
			}
		}

		protected function mouseMoveHandler(event:MouseEvent):void
		{
			switch (_dragPhase)
			{
				case MapHandlerEvent.START:
					dispatchEvent(new MouseDefaultsEvent(MouseDefaultsEvent.DRAG_START,
						map, event));
					_dragPhase=MapHandlerEvent.UPDATE;
					break;
				case MapHandlerEvent.UPDATE:
					dispatchEvent(new MouseDefaultsEvent(MouseDefaultsEvent.DRAG_UPDATE,
						map, event));
					break;
			}
		}

		protected function mouseUpHandler(event:MouseEvent):void
		{
			switch (_dragPhase)
			{
				case MapHandlerEvent.START:
					_dragPhase=MapHandlerEvent.IDLE;
					break;
				case MapHandlerEvent.UPDATE:
					_dragPhase=MapHandlerEvent.END;
					dispatchEvent(new MouseDefaultsEvent(MouseDefaultsEvent.DRAG_END,
						map, event));
					_dragPhase=MapHandlerEvent.IDLE;
					break;
			}
		}

		protected function mouseWheelHandler(event:MouseEvent):void
		{
			var where:Location=map.toMapPoint(new Point(event.stageX - map.x, event.stageY -
				map.y));
			var extent:Envelope=map.extent;
			if (event.delta > zoomThreshold)
			{
				extent.zoom(zoomStep, where);
			}
			else if (event.delta < -zoomThreshold)
			{
				extent.zoom(1 / zoomStep, where);
			}
			map.extent=extent;
			dispatchEvent(new MouseDefaultsEvent(MouseDefaultsEvent.WHEEL, map, event));
		}

		protected function clickHandler(event:MouseEvent):void
		{
			var where:Location=map.toMapPoint(new Point(event.stageX - map.x, event.stageY -
				map.y));
			var extent:Envelope=map.extent;

			if (event.shiftKey as Boolean)
			{
				extent.center=where;
				map.extent=extent;
			}
			else if (event.ctrlKey as Boolean)
			{
				extent.zoom(zoomStep, where);
				map.extent=extent;
			}
			else if (event.altKey as Boolean)
			{
				extent.zoom(1 / zoomStep, where);
				map.extent=extent;
			}

			dispatchEvent(new MouseDefaultsEvent(MouseDefaultsEvent.CLICK, map, event));
		}

		protected function dragStartHandler(event:MouseDefaultsEvent):void
		{
			map.layers.useHandCursor=true;
			map.layers.buttonMode=true;
			map.layers.mouseChildren=false;
			_origin=event.where;
			map.layers.startDrag();
		}

		protected function dragCompleteHandler(event:MouseDefaultsEvent):void
		{
			var extent:Envelope=map.extent;
			var where:Location=event.where;
			map.layers.stopDrag();
			map.layers.move(0, 0); //TODO  to make interaction without 'shadow'
			extent.pan(where.x - _origin.x, where.y - _origin.y);
			_origin=null;
			map.extent=extent;
			map.layers.mouseChildren=true;
			map.layers.buttonMode=false;
			map.layers.useHandCursor=false;
		}

	}
}
